package com.bionet.metaboservice.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.stp.StpUtil;
import com.bionet.service_base.utils.Result;
import com.mathworks.toolbox.javabuilder.MWException;
import edu.cornell.med.icb.R.RConnectionPool;
import org.rosuda.REngine.*;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author hzx
 * @create 2021-07-18 16:12
 */
@RestController
@RequestMapping("/metaboservice/enrichanalyst")
public class EnrichControllor {

    @GetMapping("GetConnection")
    public String GetConnection() throws RserveException {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        if (!tokenSession.has("rConnection")) {
            RConnectionPool connectionPool = RConnectionPool.getInstance();
            c = connectionPool.borrowConnection(10, TimeUnit.MINUTES);
            c.eval("rm(list = ls())");
            c.eval("library(MetaboAnalystR)");
            c.eval("Sys.setlocale(category = \"LC_ALL\",locale = \"English_United States.1252\")");
            tokenSession.set("historyCmd", "");
            tokenSession.set("rConnection", c);
        }
        return "ok";
    }

    @GetMapping("ReleaseConnection")
    public void ReleaseConnection() {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            c = (RConnection) tokenSession.get("rConnection");
            RConnectionPool connectionPool = RConnectionPool.getInstance();
            connectionPool.returnConnection(c);
            tokenSession.delete("rConnection");
        } finally {
            tokenSession.clear();
        }
    }

    @PostMapping("EnrichCreateTable")
    public Result EnrichCreateTable(@RequestParam(value = "cmd", required = true) String cmd) {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            // 连接 Rserve,初始化过程
            c = (RConnection) tokenSession.get("rConnection");
            tokenSession.set("enrichCreateTableCmd", cmd);
            c.eval(cmd);
            REXP eval = c.eval("(mSet[[\"dataSet\"]][[\"map.table\"]])");
            String[] strings = eval.asStrings();
            int length = strings.length / 7;
            ArrayList<HashMap<String, String>> table = new ArrayList<>();
            for (int i = 0; i < length; i++) {
                ArrayList<HashMap<String, String>> item = new ArrayList<>();
                HashMap<String, String> itemMap = new HashMap<>();
                itemMap.put("Query", strings[i + 0]);
                itemMap.put("Match", strings[i + length * 1]);
                itemMap.put("HMDB", strings[i + length * 2]);
                itemMap.put("PubChem", strings[i + length * 3]);
                itemMap.put("KEGG", strings[i + length * 4]);
                itemMap.put("SMILES", strings[i + length * 5]);
                itemMap.put("Comment", strings[i + length * 6]);
                table.add(itemMap);
            }
            String historyCmd = (String) tokenSession.get("historyCmd");
            tokenSession.set("historyCmd", historyCmd.concat("\n" + cmd));
            tokenSession.set("enrichCreateTable", table);
            return Result.ok().data("Table", table);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().data("Message", e);
        } finally {

        }
    }

    @PostMapping("EnrichGetCandidateList")
    public Result EnrichGetCandidateList(@RequestParam(value = "cmd", required = true) String cmd) {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            // 连接 Rserve
            c = (RConnection) tokenSession.get("rConnection");
            c.eval(cmd);
            REXP eval = c.eval("mSet[[\"dataSet\"]][[\"candidates\"]]");
            RList rList = eval.asList();
            REXPDouble a = (REXPDouble) rList.get(0);
            double[] index = a.asDoubles();
            REXPString b = (REXPString) rList.get(1);
            String[] value = b.asStrings();
            REXPDouble d = (REXPDouble) rList.get(2);
            double[] score = d.asDoubles();
            int length = value.length;
            ArrayList<HashMap<String, Object>> table = new ArrayList<>();
            for (int i = 0; i < length; i++) {
                ArrayList<HashMap<String, Object>> item = new ArrayList<>();
                HashMap<String, Object> itemMap = new HashMap<>();
                itemMap.put("index", index[i]);
                itemMap.put("value", value[i]);
                itemMap.put("score", score[i]);
                table.add(itemMap);
            }
            String historyCmd = (String) tokenSession.get("historyCmd");
            tokenSession.set("historyCmd", historyCmd.concat("\n" + cmd));
            tokenSession.set("candidateList", table);
            return Result.ok().data("CandidateList", table);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().data("Message", e);
        } finally {

        }
    }

    @PostMapping("EnrichSetCandidate")
    public Result EnrichSetCandidate(@RequestParam(value = "cmd", required = true) String cmd) {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            // 连接 Rserve
            c = (RConnection) tokenSession.get("rConnection");
            c.eval(cmd);
            REXP eval = c.eval("(mSet[[\"dataSet\"]][[\"map.table\"]])");
            String[] strings = eval.asStrings();
            int length = strings.length / 7;
            ArrayList<HashMap<String, String>> table = new ArrayList<>();
            for (int i = 0; i < length; i++) {
                ArrayList<HashMap<String, String>> item = new ArrayList<>();
                HashMap<String, String> itemMap = new HashMap<>();
                itemMap.put("Query", strings[i + 0]);
                itemMap.put("Match", strings[i + length * 1]);
                itemMap.put("HMDB", strings[i + length * 2]);
                itemMap.put("PubChem", strings[i + length * 3]);
                itemMap.put("KEGG", strings[i + length * 4]);
                itemMap.put("SMILES", strings[i + length * 5]);
                itemMap.put("Comment", strings[i + length * 6]);
                table.add(itemMap);
            }
            String historyCmd = (String) tokenSession.get("historyCmd");
            tokenSession.set("historyCmd", historyCmd.concat("\n" + cmd));
            tokenSession.set("enrichCreateTable", table);
            return Result.ok().data("Table", table);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().data("Message", e);
        } finally {

        }
    }

    @PostMapping("EnrichCalculate")
    public Result EnrichCalculate(@RequestParam(value = "cmd", required = true) String cmd) {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            c = (RConnection) tokenSession.get("rConnection");
            c.eval(cmd);
            REXP eval = c.eval("mSet[[\"analSet\"]][[\"ora.mat\"]]");
            REXP eval1 = c.eval("row.names(mSet[[\"analSet\"]][[\"ora.mat\"]])");
            String[] strings = eval.asStrings();
            String[] strings1 = eval1.asStrings();
            int length = strings.length / 6;
            ArrayList<HashMap<String, String>> table = new ArrayList<>();
            for (int i = 0; i < length; i++) {
                ArrayList<HashMap<String, String>> item = new ArrayList<>();
                HashMap<String, String> itemMap = new HashMap<>();
                itemMap.put("Name", strings1[i]);
                itemMap.put("Hits", strings[i + 0]);
                itemMap.put("Total", strings[i + length * 1]);
                itemMap.put("Raw p", strings[i + length * 2]);
                itemMap.put("Holm p", strings[i + length * 3]);
                itemMap.put("FDR", strings[i + length * 4]);
                itemMap.put("Expected", strings[i + length * 5]);
                table.add(itemMap);
            }
            String historyCmd = (String) tokenSession.get("historyCmd");
            tokenSession.set("historyCmd", historyCmd.concat("\n" + cmd));
            tokenSession.set("enrichCalculate", table);
            return Result.ok().data("Table", table);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().data("Message", e);
        } finally {

        }
    }

    @PostMapping("CommonSet")
    public Result CommonSet(@RequestParam(value = "cmd", required = true) String cmd) {
        RConnection c = null;
        SaSession tokenSession = StpUtil.getTokenSession();
        try {
            // 连接 Rserve
            c = (RConnection) tokenSession.get("rConnection");
            REXP eval = c.eval(cmd);
            String historyCmd = (String) tokenSession.get("historyCmd");
            tokenSession.set("historyCmd", historyCmd.concat("\n" + cmd));
            return Result.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error().data("Message", e);
        } finally {

        }
    }

    @GetMapping("GetSessionData")
    public Result GetSessionData() {
        SaSession tokenSession = StpUtil.getTokenSession();
        // 获取session中所有的键值
        Set<String> enumeration = tokenSession.keys();
        HashMap<Object, Object> SessionMap = new HashMap<>();
        // 遍历enumeration中的
        for(String item : enumeration) {
            // 根据键值取session中的值
            Object value = tokenSession.get(item);
            // 加入列表
            SessionMap.put(item, value);
        }
        return Result.ok().data("map", SessionMap);
    }
}
